package com.test.study.web;

import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.Socket;
import java.nio.charset.Charset;
import java.util.concurrent.ConcurrentHashMap;

import com.test.study.api.IHelloService;
import com.test.study.pojo.GpRpcReq;
import com.test.study.util.SerializationUtil;

public class GpRpcServerHandler implements Runnable {
	
	private Socket socket;
	private ConcurrentHashMap<String,Object> services;
	
	public GpRpcServerHandler(Socket socket, ConcurrentHashMap<String,Object> services) {
		this.socket = socket;
		this.services = services;
	}

	@Override
	public void run() {
		DataInputStream input;
		DataOutputStream output;
		try {
			input = new DataInputStream(socket.getInputStream());
            byte[] data = parseReq(input);
			GpRpcReq req = SerializationUtil.deserialize(GpRpcReq.class, data);	
			// 获取 客户端请求
			System.out.println("receive req："+req);
			Object resp = doHandler(req);
			System.out.println("receive req handle resp："+resp);
			output = new DataOutputStream(socket.getOutputStream());
			byte[] respData = resp.toString().getBytes("UTF-8");
			int len = respData.length+4;
			output.writeInt(len);
			output.write(respData);
			output.flush();
			
			output.close();
			input.close();
			
			System.out.println("receive req handle resp  send："+new String(respData,"UTF-8"));
			
		} catch (IOException e) {
			e.printStackTrace();
		} catch (Exception e) {
			e.printStackTrace();
		}

	}
	
	public byte[] parseReq(DataInputStream input) throws IOException{
		int len = input.readInt();
		byte[] data = new byte[len-4];
		input.readFully(data);
		return data;
	}

	private Object doHandler(GpRpcReq req) {
		String serviceName = req.getServiceName();
		if(null!=req.getVer()){
			serviceName=serviceName+"_"+req.getVer();
		}
		Object service = services.get(serviceName);
		if(null == service){
			throw new RuntimeException("service not found:"+service);
		}
		
		Object[] params = req.getParams();
		Class<?>[] types = new Class<?>[params.length];
		for(int i=0;i<params.length;i++){
			types[i]=params[i].getClass();
		}
		Class<?> clz ;
		try {
			clz = service.getClass();
			Method method = clz.getMethod(req.getMethodName(),types);
			if(null == method){
				throw new NoSuchMethodException();
			}
			Object result = method.invoke(service,params);
			return result;
		} catch (NoSuchMethodException e) {
			e.printStackTrace();
		} catch (SecurityException e) {
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			e.printStackTrace();
		} catch (IllegalArgumentException e) {
			e.printStackTrace();
		} catch (InvocationTargetException e) {
			e.printStackTrace();
		}
		return null;
	}

}
